package joodle.tools;

import java.awt.Graphics;
import java.awt.event.KeyEvent;

import joodle.domain.Canvas;
import joodle.domain.Point;
import joodle.domain.Shape;
import joodle.domain.ShapeFactory;
import joodle.domain.Shape.Attribute;

/**
 * CreationTool class is responsible for creation of new Shapes and adding them to Canvas. It uses a 
 * ShapeFactory for creating new Shapes. Since ShapeFactory is an interface with a makeShape method, 
 * there is no need for subclassing the CreationTool for each shape. It suffices to pass a 
 * ShapeFactory to the CreationTool and the proper shape will be created. In this way, CreationTool 
 * reifies the Command design pattern. Using this pattern creating any new kind of shape (i.e. Add-on 
 * shapes) using CreationTool is possible. CreationTool is a singleton class.
 * <p><center>
 * <img src="http://ug.bcc.bilkent.edu.tr/~m_ozdal/Site/Reports_files/design_files/image005.jpg" />
 * </center></p>
 */
public class CreatorTool implements Tool {
	
	private Shape shape;
	private final ShapeFactory factory;
	
	public CreatorTool(final ShapeFactory factory) {
		this.factory = factory;
	}
	
	/**
	 * Draws intermediate figures as an indicator of CreatorTool
	 * @see Tool#drawInterim(Graphics)
	 */
	@Override
	public void drawInterim(Graphics g) {
		if(shape == null)
			return;
		shape.draw(g);
	}

	/**
	 * Invoked when the mouse cursor has been moved onto a component. Updates the end point of the
	 * component 
	 * @see Tool#handleMove(Point, boolean, boolean)
	 */
	@Override
	public void handleMove(Point p, boolean ctrl, boolean lb) {
		if(shape == null)
			return;
		shape.updateEndPoint(p);
	}

	/**
	 * Invoked when the mouse button has been clicked (pressed and released) on a component.
	 * @see Tool#handlePress(Point, boolean)
	 */
	@Override
	public void handlePress(Point p, boolean ctrl) {
		if(shape == null) {
			shape = factory.makeShape();
			shape.addPoint(p);
		}
		if(shape.hasEnoughPoints()) {
			Canvas.instance().addShape(shape);
			shape = null;
		}
		else
			shape.addPoint(p);
	}

	/**
	 * @see Tool#handleRelease(Point, boolean)
	 */
	@Override
	public void handleRelease(Point p, boolean ctrl) {
	}

	/**
	 * Invoked when escape or backspace key has been pressed.
	 * @see Tool#handleKeyPress(int)
	 */
	@Override
	public void handleKeyPress(int c) {
		if(shape == null) 
			return;

		switch(c) {
			case KeyEvent.VK_ESCAPE:
				shape = null;
				break;
			case KeyEvent.VK_BACK_SPACE:
				String text = (String) shape.getAttributeValue(Attribute.TEXT);
				if(text != null) {
					text = text.substring(0, text.length() - 1);
					shape.setAttributeValue(Attribute.TEXT, text);
				}
				break;
			// handle other action keys
		}
	}

	/**
	 * Invoked when a key has been typed.
	 * @see Tool#handleKeyType(char)
	 */
	@Override
	public void handleKeyType(char c) {
		if(shape == null) 
			return;
		
		String text = (String) shape.getAttributeValue(Attribute.TEXT);
		if(text == null)
			return;

		shape.setAttributeValue(Attribute.TEXT, text + c);
	}
	
}
